package com.lagou.edu;


import com.lagou.edu.comment.LagouAutoware;
import com.lagou.edu.comment.LagouService;
import com.lagou.edu.comment.LagouTransactional;
import com.lagou.edu.factory.ProxyFactory;
import com.lagou.edu.service.TransferService;
import com.lagou.edu.utils.ClassUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class LagouApplyationContext {


    public Map<String, Object> beans = new HashMap<>();

    public Map<String, Class> transactional=new HashMap<>();


    public LagouApplyationContext(String scanPath)  {
       //生成bean
        prepareContext(scanPath);
        //属性注入
        initAutoware();
        //处理声明式事物
        fillTrans();

    }


    public void prepareContext(String scanPath)  {
       //获取到所有的注解类
        List<Class> annotationclass = findAllANotationClass(scanPath);
        //遍历所有 注解类生成对象放入集合
        for (Class aClass : annotationclass) {
            LagouService declaredAnnotation = (LagouService) aClass.getDeclaredAnnotation(LagouService.class);
            String id = declaredAnnotation.id();
            if ("".equals(id)){
                id=findDeafultId(aClass);
            }
            verifyTansactional(id,aClass);
            //生成了工厂
            try {
                beans.put(id,getInstance(aClass));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        }

    }

    private void fillTrans()  {
        ProxyFactory proxyFactory = (ProxyFactory) beans.get("proxyFactory");
        for (Map.Entry<String, Class> stringObjectEntry : transactional.entrySet()) {
           String beanId = stringObjectEntry.getKey();
            Object jdkProxy = proxyFactory.getJdkProxy(beans.get(beanId));
            System.out.println(jdkProxy.getClass());
            beans.put(beanId,jdkProxy);
        }

    }

    private void verifyTansactional(String id,Class clazz){
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            LagouTransactional annotation = declaredMethod.getAnnotation(LagouTransactional.class);
            if (null!=annotation){
                transactional.put(id,clazz);
            }
        }
    }


    //依赖注入设置值
    private void initAutoware()  {
        for (Map.Entry<String, Object> stringObjectEntry : beans.entrySet()) {
            try {
                fillIn(stringObjectEntry.getValue());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void fillIn(Object o) throws Exception {
        Class<?> aClass = o.getClass();
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            LagouAutoware annotation = declaredField.getAnnotation(LagouAutoware.class);
          if (annotation!=null){
              Class<?> type = declaredField.getType();
              String deafultId = findDeafultId(type);
              Object bean = getBean(deafultId);
              if (null!=bean){
                  declaredField.setAccessible(true);
                  declaredField.set(o,bean);
              }else {
                  System.out.println("11111");
              }

          }
        }
    }

    public Object getBean(String beanId){
       return beans.get(beanId);
    }

    /**
     * //通过反射创建类
     * @param classInfo
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    private Object getInstance(Class<?> classInfo) throws IllegalAccessException, InstantiationException {
        return classInfo.newInstance();
    }


    /**
     * 获取到指定包下所有的类
     * @param scanPath
     * @return
     */
    private List<Class> findAllANotationClass(String scanPath){
        //获取到包路径下的所有类
        List<Class<?>> classes = ClassUtils.getClasses(scanPath);
        //获取到注解的类
        ArrayList<Class> annotation = new ArrayList<>();
        for (Class<?> aClass : classes) {
            LagouService declaredAnnotation = aClass.getDeclaredAnnotation(LagouService.class);
            if (null!=declaredAnnotation){
                annotation.add(aClass);
            }
        }
        return annotation;
    }

    /**
     * 获取beanId 没有取默认值
     * @param aClass
     * @return
     */
    private String findDeafultId(Class aClass){
        LagouService declaredAnnotation = (LagouService) aClass.getDeclaredAnnotation(LagouService.class);
        if (null==declaredAnnotation){
            //表示是接口
            List<Class> allClassByInterface = ClassUtils.getAllClassByInterface(aClass);
            Class aClass1 = allClassByInterface.get(0);
           return findDeafultId(aClass1);
        }
        String id =declaredAnnotation.id();
        Class[] interfaces = aClass.getInterfaces();
        if ("".equals(id)){
            if (interfaces.length==0){
                id=findDeafultId(aClass.getSimpleName());
            }else {
                id=findDeafultId(interfaces[0].getSimpleName());
            }
        }
        return id;
    }

    /**
     * 获取ID
     * @param id
     * @return
     */
    private String findDeafultId(String id){
        if (Character.isLowerCase(id.charAt(0))){
            return id;
        }else {
            return (new StringBuilder()).append(Character.toLowerCase(id.charAt(0))).append(id.substring(1)).toString();
        }

    }


    public static void main(String[] args)  {
        LagouApplyationContext lagaoApplycationcontext = new LagouApplyationContext("com.lagou.edu");

        TransferService t = (TransferService) lagaoApplycationcontext.getBean("transferService");

        try {
            t.transfer("123","456",1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
